package com.ruyuan.course.basic.config.datasource;

import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

/**
 * mysql数据源配置
 *
 * @author demo
 */
@Configuration
@MapperScan(basePackages = "com.ruyuan.course.basic.biz.mapper", sqlSessionTemplateRef = "demoSqlSessionTemplate")
public class DemoDataSourceConfiguration {

    @Value("${mysql.demo.url}")
    private String  url;
    @Value("${mysql.demo.username}")
    private String  userName;
    @Value("${mysql.demo.password}")
    private String  password;
    @Value("${initialSize}")
    private int     initialsize;
    @Value("${minIdle}")
    private int     minidle;
    @Value("${maxActive}")
    private int     maxactive;
    @Value("${maxWait}")
    private int     maxwait;
    @Value("${timeBetweenEvictionRunsMillis}")
    private int     timebetweenevictionrunsmillis;
    @Value("${minEvictableIdleTimeMillis}")
    private int     minEvictableIdleTimeMillis;
    @Value("${validationQuery}")
    private String  validationQuery;
    @Value("${testWhileIdle}")
    private boolean testWhileIdle;
    @Value("${testOnBorrow}")
    private boolean testonborrow;
    @Value("${testOnReturn}")
    private boolean testonreturn;

    @Bean(name = "demoDatasource", initMethod = "init", destroyMethod = "close")
    public DruidDataSource getDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(url);
        dataSource.setUsername(userName);
        dataSource.setPassword(password);

        // 配置初始化大小、最小、最大
        dataSource.setInitialSize(initialsize);
        dataSource.setMinIdle(minidle);
        dataSource.setMaxActive(maxactive);

        //配置获取链接等待超时的时间
        dataSource.setMaxWait(maxwait);
        //配置间隔多久才能进行一次检测，检测需要关闭的控线连接，单位是毫秒
        dataSource.setTimeBetweenEvictionRunsMillis(timebetweenevictionrunsmillis);
        // 配置一个连接在池中最小生存的时间，单位是毫秒
        dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
        // 探测连接是否有效的sql
        dataSource.setValidationQuery(validationQuery);
        //连接检查 保证安全性
        dataSource.setTestWhileIdle(testWhileIdle);
        //申请连接时检查
        dataSource.setTestOnBorrow(testonborrow);
        //还连接时执行validationQuery检测连接是否有效，做了这个配置会降低性能
        dataSource.setTestOnReturn(testonreturn);
        return dataSource;
    }

    @Bean(name = "demoSqlSessionFactory")
    public SqlSessionFactory testSqlSessionFactory(@Qualifier("demoDatasource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        return bean.getObject();
    }

    @Bean(name = "demoTransactionManager")
    public DataSourceTransactionManager sentinelTransactionManager(@Qualifier("demoDatasource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "demoSqlSessionTemplate")
    public SqlSessionTemplate sentinelSqlSessionTemplate(@Qualifier("demoSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}
